package com.ice.delay.task.core.helper;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.ice.delay.task.core.config.DelayTaskConfig;

import com.ice.delay.task.core.constant.ServerErrorCode;
import com.ice.delay.task.core.enums.ExecuteStatusEnum;
import com.ice.delay.task.core.enums.NotifyStatusEnum;
import com.ice.delay.task.core.model.DelayTaskDetail;
import com.ice.framework.common.base.ResponseResult;
import lombok.extern.slf4j.Slf4j;

/**
 * @author ice
 * @Date 2022/5/14 0014 12:53
 */
@Slf4j
public class DelayTaskDetailRunnableHelper {

    /**
     * 执行任务
     *
     * @param delayTaskDetail
     */
    public static void execute(DelayTaskDetail delayTaskDetail) {
        if ("GET".equals(delayTaskDetail.getRequestMethod()) || "get".equals(delayTaskDetail.getRequestMethod())) {
            HttpResponse execute = HttpUtil.createGet(delayTaskDetail.getTaskNotifyUrl()).execute();
            handleResponse(delayTaskDetail, execute);
        }
        if ("POST".equals(delayTaskDetail.getRequestMethod()) || "post".equals(delayTaskDetail.getRequestMethod())) {
            HttpResponse execute = HttpUtil.createPost(delayTaskDetail.getTaskNotifyUrl()).body(delayTaskDetail.getRequestParam()).execute();
            handleResponse(delayTaskDetail, execute);
        }
    }

    /**
     * 解析返回的结果
     * @param delayTaskDetail
     * @param execute
     */
    private static void handleResponse(DelayTaskDetail delayTaskDetail, HttpResponse execute) {
        if (execute.isOk()) {
            // 返回的结果符合规则
            String body = execute.body();
            ResponseResult responseResult = null;
            try {
                responseResult = JSON.parseObject(body, ResponseResult.class);
                logger.debug("请求返回内容：{}", responseResult);
                if (ObjectUtil.isEmpty(responseResult) || ObjectUtil.isEmpty(responseResult.getErrorCode())) {
                    handleException(delayTaskDetail.getCode(), "返回格式错误");
                    return;
                }
            } catch (Exception e) {
                logger.debug("解析异常{}", ExceptionUtil.stacktraceToString(e));
                handleException(delayTaskDetail.getCode(), "返回格式错误");
                return;
            }
            if (ServerErrorCode.SUCCESS.equals(responseResult.getErrorCode())) {
                DelayTaskDetail task = new DelayTaskDetail();
                task.setCode(delayTaskDetail.getCode());
                task.setNotifyStatus(NotifyStatusEnum.SUCCESS.getCode());
                task.setExecuteStatus(ExecuteStatusEnum.STOP.getCode());
                Integer count = DelayTaskConfig.getDelayTaskConfig().getDelayTaskDetailService().updateDelayTask(task);
                if (count < 1){
                    logger.error("任务更新异常：{}", JSON.toJSONString(task));
                }
            } else {
                handleException(delayTaskDetail.getCode(), responseResult.getErrorMsg());
            }
        } else {
            // 异常情况下
            handleException(delayTaskDetail.getCode(), "网络错误");
        }
    }

    /**
     * 处理异常情况
     */
    private static void handleException(String code, String exceptionMessage) {
        DelayTaskDetail taskDetail = DelayTaskConfig.getDelayTaskConfig().getDelayTaskDetailService().findTaskDetail(code);
        if (NotifyStatusEnum.SUCCESS.getCode().equals(taskDetail.getNotifyStatus()) || NotifyStatusEnum.FAIL.getCode().equals(taskDetail.getNotifyStatus())) {
            // 已经成功了或者失败，重复返回
            logger.debug("编码：{}已返回，重复处理", code);
            return;
        }
        // 超过最大重试次数
        if (taskDetail.getNotifyRetryNum() >= DelayTaskConfig.getDelayTaskConfig().getRetryMaxNum()) {
            DelayTaskDetail task = new DelayTaskDetail();
            task.setCode(code);
            task.setNotifyStatus(NotifyStatusEnum.FAIL.getCode());
            task.setExecuteStatus(ExecuteStatusEnum.STOP.getCode());
            DelayTaskConfig.getDelayTaskConfig().getDelayTaskDetailService().updateDelayTask(task);
            logger.debug("编码：{}, 超过了最大重试次数，更新为失败", code);
        } else {
            DelayTaskDetail task = new DelayTaskDetail();
            task.setCode(code);
            task.setNotifyRetryNum(taskDetail.getNotifyRetryNum() + 1);
            DelayTaskConfig.getDelayTaskConfig().getDelayTaskDetailService().updateDelayTask(task);
            logger.info("编码：{}任务执行失败，重新进入时间轮中处理", code);
            // 添加到时间轮中再次执行
            DelayTaskConfig.getDelayTaskConfig().getTimerWheel().addTimerOneTime(DelayTaskConfig.getDelayTaskConfig().getRetryIntervalTime(), aVoid -> {
                // 执行任务
                DelayTaskDetailRunnableHelper.execute(taskDetail);
            });
        }
    }
}
